/*
 * @Author: YURI
 * @Date: 2022-09-11 19:42:00
 * @LastEditTime: 2022-09-27 23:24:55
 * @Description: ecall 提供API
 */
#include "easycall.h"

//easycall动态加载的库的头指针
easycall_lib_info_table_t g_easycall_lib_info_table={
    .lib_index=0
};

/**
 * @function: ecall_show_license
 * @description: 显示开源信息
 * @return {*}
 * @author: yuri
 */
void easycall_show_license(void)
{
    int ret=system("clear");
    ret = ret;
    ECALL_PRINT_LN("--------------------ECALL START------------------------");
    ECALL_PRINT_LN("AUTHOR: YURI");
    ECALL_PRINT_LN("VERSION: V1.0");
    ECALL_PRINT_LN("BUILD: "__DATE__" "__TIME__);
    ECALL_PRINT_LN("Permission is granted to anyone to use this software");
    ECALL_PRINT_LN("for any purpose on any computer system but :");
    ECALL_PRINT_LN("1.The authors are not responsible for the consequences ");
    ECALL_PRINT_LN("of use of this software");
    ECALL_PRINT_LN("2.The origin of this software must not be misrepresented,");
    ECALL_PRINT_LN("either by explicit claim or by omission");
    ECALL_PRINT_LN("--------------------ECALL END--------------------------");        
}

/**
 * @function: ecall_check_type
 * @description: 确认是不是elf文件 然后返回是32还是64
 * @param {char *} elf_path
 * @return {*}
 * @author: yuri
 */
int easycall_check_type(const char * elf_path)
{
    int ret;
    int elf_fd;
    int elf_type;
    char tmp[30];  
    elf_fd = open(elf_path, O_RDONLY);
    if(elf_fd < 0) {
        ECALL_PRINT_LN("%s not exist", elf_path);
        return -1;
    }
    //读出elf最开始的5个字节 确定是不是elf文件
    memset(tmp, 0, sizeof(tmp));
    ret=read(elf_fd,tmp,5);
    if(ret < 0)
    {
        perror("read error");
    }
    if(tmp[0] != 0x7f || tmp[1] != 'E' || tmp[2] != 'L' || tmp[3] != 'F') {
        ECALL_PRINT_LN("%s is not an ELF file", elf_path);
        return -1;
    }
    elf_type = tmp[4] == 1 ? 32 : 64;     //判断elf文件为32位还是64位
    close(elf_fd);
    return elf_type;  
}

/**
 * @function: easycall_elf64_show_libinfo
 * @description: 显示elf库信息
 * @param {Elf64_Ehdr*} ehdr
 * @return {*}
 * @author: yuri
 */
int easycall_elf64_show_libinfo(const Elf64_Ehdr* ehdr)
{
    if(ehdr == NULL)
    {
        return -1;
    }
    switch(ehdr->e_type) {
        case 0 : ECALL_PRINT_LN("Unknown file type"); break;
        case 1 : ECALL_PRINT_LN("Relocatable file"); break;
        case 2 : ECALL_PRINT_LN("Executable file"); break;
        case 3 : ECALL_PRINT_LN("Dynamic link library file"); break;
        case 4 : ECALL_PRINT_LN("Core file"); break;
        case 0xff00 : ECALL_PRINT_LN("Processor-specific file extends lower bounds"); break;
        case 0xffff : ECALL_PRINT_LN("Processor-specific file extends upper bounds"); break;
    }
    ECALL_PRINT_LN("Processor Architecture:\t\t");
    switch(ehdr->e_machine) {
        case 0 : ECALL_PRINT_LN("Unknown architecture"); break;
        case 1 : ECALL_PRINT_LN("AT&T WE 32100"); break;
        case 2 : ECALL_PRINT_LN("SPARC"); break;
        case 3 : ECALL_PRINT_LN("Intel Architecture"); break;
        case 4 : ECALL_PRINT_LN("Motorola 68000"); break;
        case 5 : ECALL_PRINT_LN("Motorola 88000"); break;
        case 7 : ECALL_PRINT_LN("Intel 80860"); break;
        case 8 : ECALL_PRINT_LN("MIPS RS3000 Big-Endian"); break;
        case 10 : ECALL_PRINT_LN("MIPS RS4000 Big-Endian"); break;
        case 62 : ECALL_PRINT_LN("AMD x86-64 architecture"); break;
    }
    ECALL_PRINT_LN("version:\t\t");
    switch(ehdr->e_version) {
        case 0 : ECALL_PRINT_LN("Invalid version number"); break;
        case 1 : ECALL_PRINT_LN("Current version Number"); break;
    }
    ECALL_PRINT_LN("Entry Virtual Address:\t\t\t\t\t0x%016lx", (long unsigned int)ehdr->e_entry);
    ECALL_PRINT_LN("Program header table offset:\t\t\t\t0x%08lx", (long unsigned int)ehdr->e_phoff);
    ECALL_PRINT_LN("Header table offset:\t\t\t\t\t0lx%08lx", (long unsigned int)ehdr->e_shoff);
    ECALL_PRINT_LN("Processor flag bit:\t\t\t\t\t%x", ehdr->e_flags);
    ECALL_PRINT_LN("ELF file header size:\t\t\t\t\t%u bytes", ehdr->e_ehsize);
    ECALL_PRINT_LN("Program header size for each entry:\t\t\t%u bytes", ehdr->e_phentsize);
    ECALL_PRINT_LN("Number of program header table entries:\t\t\t%u", ehdr->e_phnum);
    ECALL_PRINT_LN("Size of each entry in the header table:\t\t\t%u bytes", ehdr->e_shentsize);
    ECALL_PRINT_LN("Number of header table entries:\t\t\t\t%u", ehdr->e_shnum);
    ECALL_PRINT_LN("The string table is indexed in the header table:\t%u", ehdr->e_shstrndx);
    return 0;
}

/**
 * @function: elf64_load_symbols
 * @description: 64位 elf格式解析
 * @param {char *} elf_path
 * @return {*}
 * @author: yuri
 */
static int easycall_elf64_load_symbols(easycall_lib_info_t * share_lib_info)
{
    int i=0,j=0,ret=0;
    int elf_fd,length;
    const Elf64_Ehdr *header;       //ELF整体结构
    const Elf64_Shdr *sTable;       //节表
    const Elf64_Sym *symbolTable;   //符号表
    char *symbolSTable;             //符号字符串表
    Elf64_Xword sectionNumber;
    int symbolENumber;
    char* programMMap;
    struct stat st;
    elf_fd = open(share_lib_info->path , O_RDONLY);
    fstat(elf_fd, &st);
    length=st.st_size;
    programMMap =  (char*)mmap(NULL, length, PROT_READ, MAP_PRIVATE, elf_fd, 0);
    header = (Elf64_Ehdr *)programMMap;
    sTable = (Elf64_Shdr *)(programMMap + header->e_shoff);
    sectionNumber = sTable->sh_size;
    if (sectionNumber == 0)
    {
        sectionNumber = header->e_shnum;
    }
    if(g_ecall_debug_enable){
        ret=easycall_elf64_show_libinfo(header);
        if(ret < 0)
        {
            ret = -1;
            goto easycall_elf64_load_symbols_err;        
        }
    }
    share_lib_info->symbol_table.symtab_nums=0;
    share_lib_info->symbol_table.dynsym_nums=0;
    for ( i = 0; i < sectionNumber; ++i)
    {
        if (sTable[i].sh_type == SHT_SYMTAB)
        {
            symbolTable = (Elf64_Sym *)(&programMMap[sTable[i].sh_offset]);
            symbolENumber = sTable[i].sh_size / sTable[i].sh_entsize;
            symbolSTable = (char *)(&programMMap[sTable[i + 1].sh_offset]);
            share_lib_info->symbol_table.symtab_nums=symbolENumber;
            share_lib_info->symbol_table.symtab=(easycall_symbol_info_t*)malloc(sizeof(easycall_symbol_info_t)*symbolENumber );
            if(share_lib_info->symbol_table.symtab==NULL){
                ECALL_DEBUG("malloc error");
                ret = -1;
                goto easycall_elf64_load_symbols_err;
            }
            for ( j = 0; j < symbolENumber; ++j)
            {
                share_lib_info->symbol_table.symtab[j].index=j+1;
                share_lib_info->symbol_table.symtab[j].value=symbolTable[j].st_value;
                share_lib_info->symbol_table.symtab[j].size=symbolTable[j].st_size;
                share_lib_info->symbol_table.symtab[j].type=ELF64_ST_TYPE(symbolTable[j].st_info);
                share_lib_info->symbol_table.symtab[j].bind=ELF64_ST_BIND(symbolTable[j].st_info);
                share_lib_info->symbol_table.symtab[j].visibility=ELF64_ST_VISIBILITY(symbolTable[j].st_other);
                strcpy(share_lib_info->symbol_table.symtab[j].name,&symbolSTable[symbolTable[j].st_name]);
                share_lib_info->symbol_table.symtab[j].name[EASY_CALL_MAX_SYMBOL_LENGTH-1]='\0';
            }
        }else if (sTable[i].sh_type == SHT_DYNSYM){
            symbolTable = (Elf64_Sym *)(&programMMap[sTable[i].sh_offset]);
            symbolENumber = sTable[i].sh_size / sTable[i].sh_entsize;
            symbolSTable = (char *)(&programMMap[sTable[i + 1].sh_offset]);
            share_lib_info->symbol_table.dynsym_nums=symbolENumber;
            share_lib_info->symbol_table.dynsym=(easycall_symbol_info_t*)malloc(sizeof(easycall_symbol_info_t)*symbolENumber );
            if(share_lib_info->symbol_table.dynsym==NULL){
                ECALL_DEBUG("malloc error");
                ret = -1;
                goto easycall_elf64_load_symbols_err;
            }

            for ( j = 0; j < symbolENumber; ++j)
            {
                share_lib_info->symbol_table.dynsym[j].index=j+1;
                share_lib_info->symbol_table.dynsym[j].value=symbolTable[j].st_value;
                share_lib_info->symbol_table.dynsym[j].size=symbolTable[j].st_size;
                share_lib_info->symbol_table.dynsym[j].type=ELF64_ST_TYPE(symbolTable[j].st_info);
                share_lib_info->symbol_table.dynsym[j].bind=ELF64_ST_BIND(symbolTable[j].st_info);
                share_lib_info->symbol_table.dynsym[j].visibility=ELF64_ST_VISIBILITY(symbolTable[j].st_other);
                strcpy(share_lib_info->symbol_table.dynsym[j].name,&symbolSTable[symbolTable[j].st_name]);
                share_lib_info->symbol_table.dynsym[j].name[EASY_CALL_MAX_SYMBOL_LENGTH-1]='\0'; 
            }
        }
    }
easycall_elf64_load_symbols_err: 
    munmap(programMMap, length);
    close(elf_fd);
    return ret;  
}


/**
 * @function: easycall_elf32_show_libinfo
 * @description: 显示elf库信息
 * @param {Elf32_Ehdr*} ehdr
 * @return {*}
 * @author: yuri
 */
int easycall_elf32_show_libinfo(const Elf32_Ehdr* ehdr)
{
    if(ehdr == NULL)
    {
        return -1;
    }
    switch(ehdr->e_type) {
        case 0 : ECALL_PRINT_LN("Unknown file type"); break;
        case 1 : ECALL_PRINT_LN("Relocatable file"); break;
        case 2 : ECALL_PRINT_LN("Executable file"); break;
        case 3 : ECALL_PRINT_LN("Dynamic link library file"); break;
        case 4 : ECALL_PRINT_LN("Core file"); break;
        case 0xff00 : ECALL_PRINT_LN("Processor-specific file extends lower bounds"); break;
        case 0xffff : ECALL_PRINT_LN("Processor-specific file extends upper bounds"); break;
    }
    ECALL_PRINT_LN("Processor Architecture:\t\t");
    switch(ehdr->e_machine) {
        case 0 : ECALL_PRINT_LN("Unknown architecture"); break;
        case 1 : ECALL_PRINT_LN("AT&T WE 32100"); break;
        case 2 : ECALL_PRINT_LN("SPARC"); break;
        case 3 : ECALL_PRINT_LN("Intel Architecture"); break;
        case 4 : ECALL_PRINT_LN("Motorola 68000"); break;
        case 5 : ECALL_PRINT_LN("Motorola 88000"); break;
        case 7 : ECALL_PRINT_LN("Intel 80860"); break;
        case 8 : ECALL_PRINT_LN("MIPS RS3000 Big-Endian"); break;
        case 10 : ECALL_PRINT_LN("MIPS RS4000 Big-Endian"); break;
        case 62 : ECALL_PRINT_LN("AMD x86-64 architecture"); break;
    }
    ECALL_PRINT_LN("version:\t\t");
    switch(ehdr->e_version) {
        case 0 : ECALL_PRINT_LN("Invalid version number"); break;
        case 1 : ECALL_PRINT_LN("Current version Number"); break;
    }
    ECALL_PRINT_LN("Entry Virtual Address:\t\t\t\t\t0x%016x", ehdr->e_entry);
    ECALL_PRINT_LN("Program header table offset:\t\t\t\t0x%08x", ehdr->e_phoff);
    ECALL_PRINT_LN("Header table offset:\t\t\t\t\t0x%08lx", (long unsigned int)ehdr->e_shoff);
    ECALL_PRINT_LN("Processor flag bit:\t\t\t\t\t%x", ehdr->e_flags);
    ECALL_PRINT_LN("ELF file header size:\t\t\t\t\t%u bytes", ehdr->e_ehsize);
    ECALL_PRINT_LN("Program header size for each entry:\t\t\t%u bytes", ehdr->e_phentsize);
    ECALL_PRINT_LN("Number of program header table entries:\t\t\t%u", ehdr->e_phnum);
    ECALL_PRINT_LN("Size of each entry in the header table:\t\t\t%u bytes", ehdr->e_shentsize);
    ECALL_PRINT_LN("Number of header table entries:\t\t\t\t%u", ehdr->e_shnum);
    ECALL_PRINT_LN("The string table is indexed in the header table:\t%u", ehdr->e_shstrndx);
    return 0;
}

/**
 * @function: elf32_load_symbols
 * @description: 32位 elf格式解析
 * @param {char *} elf_path
 * @return {*}
 * @author: yuri
 */
static int easycall_elf32_load_symbols(easycall_lib_info_t * share_lib_info)
{
    int i=0,j=0,ret=0;
    int elf_fd,length;
    const Elf32_Ehdr *header;       //ELF整体结构
    const Elf32_Shdr *sTable;       //节表
    const Elf32_Sym *symbolTable;   //符号表
    char *symbolSTable;             //符号字符串表
    Elf32_Xword sectionNumber;
    int symbolENumber;
    char* programMMap;
    struct stat st;
    elf_fd = open(share_lib_info->path , O_RDONLY);
    fstat(elf_fd, &st);
    length=st.st_size;
    programMMap =  (char*)mmap(NULL, length, PROT_READ, MAP_PRIVATE, elf_fd, 0);
    header = (Elf32_Ehdr *)programMMap;
    sTable = (Elf32_Shdr *)(programMMap + header->e_shoff);
    sectionNumber = sTable->sh_size;
    if (sectionNumber == 0)
    {
        sectionNumber = header->e_shnum;
    }
    if(g_ecall_debug_enable){
        ret=easycall_elf32_show_libinfo(header);
        if(ret < 0)
        {
            ret = -1;
            goto easycall_elf32_load_symbols_err;        
        }
    }
    share_lib_info->symbol_table.symtab_nums=0;
    share_lib_info->symbol_table.dynsym_nums=0;
    for ( i = 0; i < sectionNumber; ++i)
    {
        if (sTable[i].sh_type == SHT_SYMTAB)
        {
            symbolTable = (Elf32_Sym *)(&programMMap[sTable[i].sh_offset]);
            symbolENumber = sTable[i].sh_size / sTable[i].sh_entsize;
            symbolSTable = (char *)(&programMMap[sTable[i + 1].sh_offset]);
            share_lib_info->symbol_table.symtab_nums=symbolENumber;
            share_lib_info->symbol_table.symtab=(easycall_symbol_info_t*)malloc(sizeof(easycall_symbol_info_t)*symbolENumber );
            if(share_lib_info->symbol_table.symtab==NULL){
                ECALL_DEBUG("malloc error");
                ret = -1;
                goto easycall_elf32_load_symbols_err;
            }
            for ( j = 0; j < symbolENumber; ++j)
            {
                share_lib_info->symbol_table.symtab[j].index=j+1;
                share_lib_info->symbol_table.symtab[j].value=symbolTable[j].st_value;
                share_lib_info->symbol_table.symtab[j].size=symbolTable[j].st_size;
                share_lib_info->symbol_table.symtab[j].type=ELF64_ST_TYPE(symbolTable[j].st_info);
                share_lib_info->symbol_table.symtab[j].bind=ELF64_ST_BIND(symbolTable[j].st_info);
                share_lib_info->symbol_table.symtab[j].visibility=ELF64_ST_VISIBILITY(symbolTable[j].st_other);
                strcpy(share_lib_info->symbol_table.symtab[j].name,&symbolSTable[symbolTable[j].st_name]);
                share_lib_info->symbol_table.symtab[j].name[EASY_CALL_MAX_SYMBOL_LENGTH-1]='\0';
            }
        }else if (sTable[i].sh_type == SHT_DYNSYM){
            symbolTable = (Elf32_Sym *)(&programMMap[sTable[i].sh_offset]);
            symbolENumber = sTable[i].sh_size / sTable[i].sh_entsize;
            symbolSTable = (char *)(&programMMap[sTable[i + 1].sh_offset]);
            share_lib_info->symbol_table.dynsym_nums=symbolENumber;
            share_lib_info->symbol_table.dynsym=(easycall_symbol_info_t*)malloc(sizeof(easycall_symbol_info_t)*symbolENumber );
            if(share_lib_info->symbol_table.dynsym==NULL){
                ECALL_DEBUG("malloc error");
                ret = -1;
                goto easycall_elf32_load_symbols_err;
            }

            for ( j = 0; j < symbolENumber; ++j)
            {
                share_lib_info->symbol_table.dynsym[j].index=j+1;
                share_lib_info->symbol_table.dynsym[j].value=symbolTable[j].st_value;
                share_lib_info->symbol_table.dynsym[j].size=symbolTable[j].st_size;
                share_lib_info->symbol_table.dynsym[j].type=ELF64_ST_TYPE(symbolTable[j].st_info);
                share_lib_info->symbol_table.dynsym[j].bind=ELF64_ST_BIND(symbolTable[j].st_info);
                share_lib_info->symbol_table.dynsym[j].visibility=ELF64_ST_VISIBILITY(symbolTable[j].st_other);
                strcpy(share_lib_info->symbol_table.dynsym[j].name,&symbolSTable[symbolTable[j].st_name]);
                share_lib_info->symbol_table.dynsym[j].name[EASY_CALL_MAX_SYMBOL_LENGTH-1]='\0'; 
            }
        }
    }
easycall_elf32_load_symbols_err: 
    munmap(programMMap, length);
    close(elf_fd);
    return ret;  
}

/**
 * @function: easycall_load_library
 * @description: 
 * @param {char} *lib_path
 * @return {*}
 * @author: yuri
 */
int easycall_load_library(const char *lib_path)
{
    int i ;
    int elf_type=0;
    easycall_lib_info_t * easycall_lib = &g_easycall_lib_info_table.lib_table[g_easycall_lib_info_table.lib_index];
    char real_path[PATH_MAX];

    if (realpath(lib_path, real_path)) {
        real_path[PATH_MAX - 1] = 0;
    } else {
        perror("realpath");
        return -1;
    }

    memcpy(easycall_lib->path , real_path , strlen(real_path));
    for(i = 0; i < g_easycall_lib_info_table.lib_index ; i++) {
        if(0 == strcmp(g_easycall_lib_info_table.lib_table[i].path , real_path)) {
            ECALL_PRINT_LN("%s is already loaded!", real_path);
            return -1;
        }
    }

    elf_type = easycall_check_type(real_path);
    ECALL_PRINT_LN("%s:it is a %d elf library",real_path,elf_type);

    if(elf_type == 64)
    {
        easycall_elf64_load_symbols(easycall_lib);
    }else if(elf_type == 32)
    {
        easycall_elf32_load_symbols(easycall_lib);
    }
    else{
        return -2;
    }

    easycall_lib->handle = dlopen(easycall_lib->path , RTLD_NOW | RTLD_GLOBAL);
    if(easycall_lib->handle == NULL){
        ECALL_PRINT_LN("dlopen error");
        return -3;
    }
    
    g_easycall_lib_info_table.lib_index++;

    return 0;
}

/**
 * @function: easycall_show_symbols
 * @description: 显示所有的符号
 * @param {easycall_symbol_table_t} symbol_table
 * @return {*}
 * @author: yuri
 */
void easycall_show_symbols(easycall_symbol_table_t symbol_table)
{
    int i=0,j=0;
    easycall_symbol_info_t* symbol_info;
    int s_len;
    ECALL_PRINT_LN("Index\tValue\tSize\tType\tBind\tVis\tNdx\tName");
    for(i=0 ; i < 2 ; i++){
        if (i == 0){
            symbol_info=symbol_table.symtab;
            s_len=symbol_table.symtab_nums;
            ECALL_PRINT_LN("SYMTAB:");
        }else{
            symbol_info=symbol_table.dynsym;
            s_len=symbol_table.dynsym_nums; 
            ECALL_PRINT_LN("DYNSYM:");           
        }
        
        for (j = 0; j < s_len; ++j)
        {
            ECALL_PRINT("%6lu\t%016lx\t%5lu\t", (long unsigned int)j, (long unsigned int)symbol_info[j].value, (long unsigned int)symbol_info[j].size);
            switch (symbol_info[j].type)
            {
            case STT_NOTYPE:
                ECALL_PRINT("NOTYPE\t");
                break;
            case STT_OBJECT:
                ECALL_PRINT("OBJECT\t");
                break;
            case STT_FUNC:
                ECALL_PRINT("FUNC\t");
                break;
            case STT_SECTION:
                ECALL_PRINT("SECTION\t");
                break;
            case STT_FILE:
                ECALL_PRINT("FILE\t");
                break;
            case STT_COMMON:
                ECALL_PRINT("COMMON\t");
                break;
            case STT_TLS:
                ECALL_PRINT("TLS\t");
                break;
            default:
                ECALL_PRINT("Unknown\t");
                break;
            }
            switch (symbol_info[j].bind)
            {
            case STB_LOCAL:
                ECALL_PRINT("LOCAL\t");
                break;
            case STB_GLOBAL:
                ECALL_PRINT("GLOBAL\t");
                break;
            case STB_WEAK:
                ECALL_PRINT("WEAK\t");
                break;
            default:
                ECALL_PRINT("Unknown\t");
            }
            switch (symbol_info[j].visibility)
            {
            case STV_DEFAULT:
                ECALL_PRINT("DEFAULT\t");
                break;
            case STV_INTERNAL:
                ECALL_PRINT("INTERNAL\t");
                break;
            case STV_HIDDEN:
                ECALL_PRINT("HIDDEN\t");
                break;
            case STV_PROTECTED:
                ECALL_PRINT("PROTECTED\t");
                break;
            default:
                ECALL_PRINT("Unknown\t");
                break;
            }
            ECALL_PRINT_LN("%.25s", symbol_info[j].name);
        }  
    }  
}

/**
 * @function: easycall_analyse_func
 * @description: 分析函数
 * @param {char *} arg
 * @return {*}
 * @author: yuri
 */
easycall_func_info_t easycall_analyse_func(const char * arg)
{
    int index=0 , i;
    char *temp;
    char ori_str[EASY_CALL_MAX_PERA_LENGTH];
    char* str = (char*)malloc(strlen(arg)*sizeof(char)+1);
    easycall_func_info_t easycall_func_info;
    strcpy(str,arg);
    char *p = strtok(str, " ");
    while(p != NULL){
        memset(ori_str,0,EASY_CALL_MAX_PERA_LENGTH);
        if(index >= EASY_CALL_MAX_PERA_LENGTH+1)break;
        if(index == 0 )
        {
            strcpy(easycall_func_info.name ,p);
        }else{
            strcpy(ori_str ,p);
            if(ori_str[0] == '\"')
            {
                easycall_func_info.pera_type[index-1]=EASYCALL_PERA_STR;
                strcpy(easycall_func_info.pera[index-1].arg_str ,&ori_str[1]);
                for(i=0;i<EASY_CALL_MAX_PERA_LENGTH;i++){
                    if(easycall_func_info.pera[index-1].arg_str[i] == '\"')
                        easycall_func_info.pera[index-1].arg_str[i] = 0;                    
                }
            }else{
                easycall_func_info.pera_type[index-1]=EASYCALL_PERA_INTER;
                easycall_func_info.pera[index-1].arg_inter=strtoul(ori_str , &temp ,0);
            }
        }
        p = strtok(NULL, " ");
        index ++;
    }
    easycall_func_info.pera_nums=index-1;
    // ECALL_PRINT_LN("%s",easycall_func_info.name);
    // for( i =0 ;i < easycall_func_info.pera_nums;i++)
    // {
    //     ECALL_PRINT_LN("%s",easycall_func_info.pera[i]);
    // }
    free(str);
    return easycall_func_info;
}

/**
 * @function: easycall_find_symbols
 * @description: 在库中找一找有没有对应的符号
 * @param {easycall_lib_info_t} lib_info
 * @param {char *} symbol_name
 * @return easycall_func_t
 * @author: yuri
 */
easycall_func_t easycall_find_symbols(easycall_lib_info_t lib_info ,char * symbol_name)
{
    int i = 0 , j =0 ,s_len = 0;
    easycall_func_t func;
    easycall_symbol_info_t* symbol_info;
    for(i=0 ; i < 2 ; i++){
        if (i == 0){
            symbol_info=lib_info.symbol_table.symtab;
            s_len=lib_info.symbol_table.symtab_nums;
        }else{
            symbol_info=lib_info.symbol_table.dynsym;
            s_len=lib_info.symbol_table.dynsym_nums; 
        }
        
        for (j = 0; j < s_len; ++j)
        {
            if(0 == strcmp(symbol_info[j].name , symbol_name)) {
                //ECALL_PRINT_LN("find symbol %s",symbol_name);
                func=dlsym(lib_info.handle,symbol_name);
                return func;
            }
        }
    }
    return NULL;
}

/**
 * @function: easycall_call_function
 * @description: 寻找到对应的符号
 * @param {easycall_func_info_t} easycall_func_info
 * @return {*}
 * @author: yuri
 */
int easycall_call_function(easycall_func_info_t easycall_func_info)
{
    int i=0 ;
    uint64_t fun_ret;
    easycall_func_t func=NULL,temp;
    void *arg[10];
    easycall_func_null_t temp_func0;
    easycall_func_args_t temp_func1;

    for(i = 0 ; i< g_easycall_lib_info_table.lib_index ; i++ )
    {
        temp=easycall_find_symbols(g_easycall_lib_info_table.lib_table[i],easycall_func_info.name);
        if(temp!=NULL)func = temp;
    }
    if(func==NULL){
        ECALL_PRINT_LN("don't find such func");
        return -1;
    }
    for(i=0 ; i<easycall_func_info.pera_nums;i++)
    {
        if(easycall_func_info.pera_type[i] == EASYCALL_PERA_INTER)
            arg[i] = (void*)easycall_func_info.pera[i].arg_inter;
        else{
            arg[i] = (void*)easycall_func_info.pera[i].arg_str;
        }
    }
    switch (easycall_func_info.pera_nums)
    {
    case 0:
        temp_func0=(easycall_func_null_t)func;
        fun_ret=temp_func0();
        break;
    case 1:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0]);
        break;   
    case 2:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1]);
        break;  
    case 3:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2]);
        break;  
    case 4:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3]);
        break;  
    case 5:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4]);
        break;  
    case 6:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5]);
        break;  
    case 7:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6]);
        break;  
    case 8:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7]);
        break;  
    case 9:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7],arg[8]);
        break;  
    case 10:
        temp_func1=(easycall_func_args_t)func;
        fun_ret=temp_func1(arg[0],arg[1],arg[2],arg[3],arg[4],arg[5],arg[6],arg[7],arg[8],arg[9]);
        break; 
    default:
        ECALL_PRINT_LN("too much perameteas");
        return -1;
    }
    ECALL_PRINT_LN("%s return: 0x%lx(%ld)",easycall_func_info.name,(uint64_t)fun_ret,(uint64_t)fun_ret);

    return 0;
}

/**
 * @function: easycall_server_printf
 * @description: 分为两种模式的打印
 * @param {char*} fmt
 * @return {*}
 * @author: Once day
 */
int easycall_server_printf(const char* fmt, ...)
{
    int i;
    va_list ap;
    int32_t str_len;
    static char buf[EASY_CALL_MAX_LINE];
    va_start(ap, fmt);

   if(g_ecall_ctl.mode  != ECALL_SERVER_MODE) {
        vsnprintf(buf, EASY_CALL_MAX_LINE - 1, fmt, ap);
        str_len = strlen(buf);
        buf[str_len] = '\0';
        printf("%s",buf);
    }
     else {
        vsnprintf(buf, EASY_CALL_MAX_LINE - sizeof(uds_command_t) - 1, fmt, ap);
        str_len = strlen(buf);
        for (i = 0; i < UDS_MAX_CLIENT; i++) {
            if (g_ecall_ctl.server->conn[i].inuse) {
                send(g_ecall_ctl.server->conn[i].client_fd, buf, str_len, MSG_NOSIGNAL);
            }
        }
    }
    va_end(ap);
    return 0;
}

/**
 * @function: easycall_system
 * @description: 
 * @param {char} *cmd
 * @return {*}
 * @author: yuri
 */
int easycall_system(const char *cmd)
{
    int ret;
    char shell_ret[EASY_CALL_MAX_SHELL_RET];
    char ficmd[EASY_CALL_MAX_LINE+10];
    memset(ficmd,0, sizeof(ficmd));
    sprintf(ficmd ,"%s >> %s",cmd,EASY_CALL_SHELL_OUT);
    if(g_ecall_ctl.mode  != ECALL_SERVER_MODE) {
        ret=system(cmd);
    }else{
        ret=system(ficmd);
    }
    if(g_ecall_ctl.mode == ECALL_SERVER_MODE)
    {
        memset(shell_ret,0, sizeof(shell_ret));
        easycall_get_shell(shell_ret);
        ECALL_PRINT("%s",shell_ret);
    }
    return ret;
}
/**
 * @function: easycall_get_shell
 * @description: 得到shell输出文件内容
 * @param {char*} buf
 * @return {*}
 * @author: yuri
 */
int easycall_get_shell(char* buf)
{
    int fd;
    int ret;
    fd=open(EASY_CALL_SHELL_OUT,O_RDWR);
    if( fd < 0)
    {
        perror("shell file");
        return -1;
    }
    ret = read(fd,buf,EASY_CALL_MAX_SHELL_RET);
    if( ret < 0)
    {
        perror("read error");
        return -1;
    }    
    ret = ftruncate(fd,0);
    if( ret < 0)
    {
        perror("read error");
        return -1;
    }    
    close(fd);
    return 0;
}